home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / tp_dmx20.zip / DMXDFILE.PAS < prev    next >
Pascal/Delphi Source File  |  1990-01-15  |  8KB  |  290 lines

  1. Unit DMXdFILE;
  2.  
  3. {$V-,I- }
  4.  
  5. (*
  6.   There are two DMX objects available for access to dBASE files:
  7.  
  8.        dBMXwindow has been written to edit small files in memory,
  9.        with a predefined number of records.
  10.  
  11.        dBrowser is for larger files.  Its DataAt function has been rewritten
  12.        in order to get records from the disk, one-at-a-time.
  13.        An artificially high number of bytes should be passed to OpenBuffer
  14.        so that DMX will allow a large number of records.
  15.  
  16.        The file DBENTRY.PAS demonstrates how these procedures are used.
  17.  *)
  18.  
  19. interface
  20.  
  21. uses   Dos, Crt, DMX2, DMX_FILE;
  22.  
  23.  
  24. type
  25.        dBMXwindow   = object (Dwindow)
  26.                         fheader  : array [0..MaxFields] of headertype;
  27.  
  28.                         procedure dBASEopen (var Data; Size : longint; var F );
  29.                         procedure dBASEwrite(var Data;  var F );
  30.  
  31.                         procedure dBASEnew;  virtual;
  32.                       end;
  33.  
  34.  
  35.        dBrowser     = object (dBMXwindow)
  36.                         dbfrecord  : array [0..255] of char;
  37.                         workfile   : dbfile;
  38.  
  39.                         procedure EvaluateRecord (RecNum :longint; Line :word);
  40.                                   virtual;
  41.                         function  DataAt (recnum : longint) : pointer;
  42.                                   virtual;
  43.                         procedure ZeroizeRecord (var Data );
  44.                                   virtual;
  45.  
  46.                         procedure dBASEinit (Filename : pathstr);
  47.                         procedure dBASEclose;
  48.                       end;
  49.  
  50.  
  51. implementation
  52.  
  53.  
  54.   { ─────────────────────────────────────────────────────────────────────── }
  55.  
  56.  
  57. procedure dBMXwindow.dBASEnew;
  58. { virtual procedure for new setup }
  59. var  i,j,k,l,m  : word;
  60.      AStr       : string;
  61. begin
  62.   i := 0;
  63.   If dataleader > 1 then
  64.     begin
  65.     InitializeField (fheader [1], '000', 'C', pred (dataleader), 0);
  66.     Inc (i);
  67.     end;
  68.  
  69.   l := totalfields;
  70.   If dataleader  > 1 then Inc (l);
  71.  
  72.   If datatrailer > 0 then
  73.     begin
  74.     InitializeField (fheader [succ (totalfields)], 'XXX', 'C', datatrailer, 0);
  75.     Inc (l);
  76.     end;
  77.  
  78.   InitializeHeader (fheader, l, recordsize, False);
  79.   FillChar (fheader [succ (l)], 1, #13);
  80.  
  81.   For j := 1 to totalfields do
  82.     begin
  83.     AStr := copy (title,
  84.                   screentab [j],
  85.                   (screentab [succ (j)])-(screentab [j])-1);
  86.     While AStr [length (AStr)] = ' ' do Dec (AStr [0]);
  87.     While (length (AStr) > 0) and (AStr [1] = ' ') do Delete (AStr,1,1);
  88.     If AStr = '' then
  89.       Str (j:0,AStr)
  90.      else
  91.       begin
  92.       If length (AStr) > 11 then AStr [0] := #11;
  93.       For m := 1 to length (AStr) do AStr [m] := upcase (AStr [m]);
  94.       end;
  95.     If upcase (datatype [j]) = 'N' then
  96.       begin
  97.       l := 0;
  98.       k := screentab [j];
  99.       While (k < screentab [succ (j)] - 1) and (dataformat [k] <> '.') do
  100.         Inc (k);
  101.       Inc (k);
  102.       While (k < screentab [succ (j)] - 1) do
  103.         begin
  104.         If upcase (dataformat [k]) = 'N' then Inc (l);
  105.         Inc (k);
  106.         end;
  107.       InitializeField (fheader [i + j],  AStr, 'N', datatab [i + j], l);
  108.       end
  109.      else
  110.       begin
  111.       InitializeField (fheader [i + j],  AStr, 'C', datatab [i + j], 0);
  112.       end;
  113.     end;
  114. end;  { dBASEnew }
  115.  
  116.  
  117.   { ─────────────────────────────────────────────────────────────────────── }
  118.  
  119.  
  120. procedure dBMXwindow.dBASEopen (var Data;  Size : longint;  var F );
  121. var  i : word;
  122. begin
  123.   If Size > 0 then FillChar (Data, Size, ' ');
  124.   If dataleader = 0 then
  125.     AdjustRecSize (1,0,0);
  126.        { This accounts for the one byte in front of each record,
  127.          which is expected by dBASE.
  128.  
  129.          The second parameter would indicate how many undisplayed bytes
  130.          there may be at the end of each record.
  131.  
  132.          The third parameter would represent how many bytes to add (or
  133.          subtract, if negative) to the working record size.
  134.          This is an advanced feature called "phantom bytes".
  135.  
  136.          Note that each call to AdjustRecSize is cumulative. }
  137.  
  138.   If filerec (F).mode = fmClosed then
  139.     begin
  140.     Reset (dbfile (F));
  141.     DiskError := IoResult;
  142.     end
  143.    else
  144.     DiskError := 0;
  145.   If DiskError = 0 then
  146.     begin
  147.     ReadNextBlock (F, fheader, (succ (totalfields) * sizeof (headertype)) + 1);
  148.     If not IoError and (Size > 0) then
  149.       begin
  150.       recordlimit := fheader [0].numrecs;
  151.       LoadDataBlock (Data, Size, F);
  152.       end;
  153.     end
  154.    else
  155.     begin
  156.     dBASEnew;
  157.     fheader [0].numrecs := recordlimit;
  158.     ReWrite (dbfile (F));
  159.     If not IoError then
  160.       begin
  161.       Close (dbfile (F));
  162.       Reset (dbfile (F));
  163.       If not IoError then
  164.         begin
  165.         WriteNextBlock (F, fheader, fheader [0].headerlen);
  166.         DiskError := IoResult;
  167.         end;
  168.       end;
  169.     end;
  170. end;  { dBASEopen }
  171.  
  172.  
  173.   { ─────────────────────────────────────────────────────────────────────── }
  174.  
  175.  
  176. procedure dBMXwindow.dBASEwrite (var Data;  var F );
  177. { use this if you are editing the whole file in memory }
  178. var    i  : word;
  179. begin
  180.   If filerec (F).mode = fmClosed then
  181.     begin
  182.     Reset (dbfile (F));
  183.     If IoError then
  184.       begin
  185.       ReWrite (dbfile (F));
  186.       DiskError := IoResult;
  187.       end;
  188.     end
  189.    else
  190.     DiskError := 0;
  191.   If DiskError = 0 then
  192.     begin
  193.     fheader [0].numrecs := recordlimit;
  194.     WriteNextBlock (F, fheader, fheader [0].headerlen);
  195.     If not IoError then SaveDataBlock (Data, F);
  196.     end;
  197. end;  { dBASEwrite }
  198.  
  199.  
  200.  
  201.   { ─────────────────────────────────────────────────────────────────────── }
  202.  
  203.  
  204. procedure dBrowser.EvaluateRecord (RecNum : longint;  Line : word);
  205. { this virtual method writes a record to the disk after every change }
  206. var  filler : array [0..255] of char;
  207. begin
  208.   If changemade then
  209.     begin
  210.     If fheader [0].numrecs < RecNum + 1 then
  211.       begin
  212.       If fheader [0].numrecs < RecNum then
  213.         begin
  214.         FillChar (filler, sizeof (filler), ' ');
  215.         SeekByte (workfile,
  216.                   fheader [0].headerlen + (fheader [0].numrecs * recordsize));
  217.         While (IoResult = 0) and (fheader [0].numrecs < RecNum) do
  218.           begin
  219.           WriteNextBlock (workfile, filler, recordsize);
  220.           Inc (fheader [0].numrecs);
  221.           end;
  222.         end;
  223.       fheader [0].numrecs := RecNum + 1;
  224.       end;
  225.     SeekByte (workfile, fheader [0].headerlen + (recnum * recordsize));
  226.     WriteNextBlock (workfile, dbfrecord, recordsize);
  227.     changemade := False;
  228.     end;
  229. end;  { EvaluateRecord }
  230.  
  231.  
  232. function  dBrowser.DataAt (recnum : longint) : pointer;
  233. { this virtual method retrieves the record from the file }
  234. begin
  235.   FillChar (dbfrecord, sizeof (dbfrecord), ' ');
  236.   SeekByte (workfile, fheader [0].headerlen + (recnum * recordsize));
  237.   ReadNextBlock (workfile, dbfrecord, recordsize);
  238.   DiskError := IoResult;
  239.   DataAt := addr (dbfrecord);
  240. end;
  241.  
  242.  
  243. procedure dBrowser.ZeroizeRecord (var Data );
  244. { this virtual method zeroizes the record from the file after a ^Y }
  245. begin
  246.   FillChar (dbfrecord, sizeof (dbfrecord), ' ');
  247.   DisplayRecord (Data, linenumber);
  248.   SeekByte (workfile, fheader [0].headerlen + (currentrec * recordsize));
  249.   WriteNextBlock (workfile, dbfrecord, recordsize);
  250.   fieldnum   := 1;
  251.   changemade := False;
  252. end;
  253.  
  254.  
  255.   { ─────────────────────────────────────────────────────────────────────── }
  256.  
  257.  
  258. procedure dBrowser.dBASEinit (Filename : pathstr);
  259. { use this if you are editing the file on disk }
  260. var  Data : byte;
  261. begin
  262.   Assign (workfile,Filename);
  263.   dBASEopen (Data, 0, workfile);
  264. end;
  265.  
  266.  
  267.  
  268.   { ─────────────────────────────────────────────────────────────────────── }
  269.  
  270.  
  271. procedure dBrowser.dBASEclose;
  272. { use this if you are editing the file on disk }
  273. begin
  274.   If filerec (workfile).mode <> fmClosed then
  275.     begin
  276.     Seek (workfile, 0);
  277.     WriteNextBlock (workfile, fheader, 32);
  278.     DiskError := IoResult;
  279.     Close (workfile);
  280.     end;
  281. end;
  282.  
  283.  
  284.  
  285.   { ─────────────────────────────────────────────────────────────────────── }
  286.  
  287.  
  288.  
  289. End.
  290.